package nl.xvr.server.web;

import java.util.Calendar;

public class ThreadSafeMessageQueue {

	// Total queue size
	private static final int QUEUE_SIZE = 8;
	// Queue
	private String[] queue = new String[QUEUE_SIZE];
	// Pointer for current position in queue
	private int queuePointer = 0;
	// Flag to indicate whether or not the queue is locked for writing
	private boolean isLocked = false;

	/**
	 * Gets the first message from the queue.
	 * 
	 * @return The first message from the queue.
	 */
	public synchronized String get() {
		try {
			while (!this.isLocked) {
				try {
					// Wait until the queue is unlocked or has logs
					wait();
				} catch (InterruptedException e) {
				}
			}
			System.out.println("GET: "
					+ Calendar.getInstance().getTimeInMillis());
			String log = this.queue[0];
			this.queue[0] = null;
			return log;
		} finally {
			this.shiftQueue();
			this.isLocked = false;
			notifyAll();
		}
	}

	/**
	 * Adds a message to the queue.
	 * 
	 * @param message
	 *            The message to add to the queue.
	 */
	public synchronized void add(String message) {
		while (this.isLocked || this.isFull()) {
			try {
				// Wait until the queue is unlocked or has space to use
				wait();
			} catch (InterruptedException e) {
			}
		}
		System.out.println("ADD: " + Calendar.getInstance().getTimeInMillis());
		this.queue[queuePointer++] = message;
		this.isLocked = true;
		notifyAll();
	}

	/**
	 * Checks whether the queue is empty or not.
	 * 
	 * @return True if the queue is empty, false otherwise.
	 */
	public boolean isEmpty() {
		return this.queuePointer <= 0;
	}

	/**
	 * Checks whether the queue is full or not.
	 * 
	 * @return True if the queue is full, false otherwise.
	 */
	public boolean isFull() {
		return this.queuePointer >= QUEUE_SIZE;
	}

	/**
	 * Shifts all items in the queue one position to the left.
	 */
	private void shiftQueue() {
		if (!this.isEmpty()) {
			for (int i = 1; i < this.queuePointer; i++) {
				// Shift item left
				this.queue[i - 1] = this.queue[i];
				this.queue[i] = null;
			}
			// Set pointer
			this.queuePointer--;
		}
	}
}
